////////////////////////////////////////////////////////////////////////////////
//
//  Copyright
//
////////////////////////////////////////////////////////////////////////////////

package ru.goodcore.utils {

import flash.display.Stage;
import flash.utils.Timer;
import flash.display.LoaderInfo;
import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.display.Sprite;

[Exclude(kind="property", name="currentCount")]
[Exclude(kind="property", name="repeatCount")]
[Exclude(kind="method", name="reset")]
[Exclude(kind="event", name="timerComplete")]

/**
 * @author					BlooDHounD
 * @version					1.0
 * @playerversion			Flash 9
 * @langversion				3.0
 * 
 * @keyword					activitylistener, activity, listener, fps, memory
 */
public class FrameTimer extends Timer {

	//-------------------------------------------------------------------------
	//
	//  Private class constants
	//
	//-------------------------------------------------------------------------

	/**
	 * @private 
	 */
	private static var _frameRate:	Number = 1E3 / 12;

	//-------------------------------------------------------------------------
	//
	//  Private class methods
	//
	//-------------------------------------------------------------------------

	public static function get frameRate():uint {
		return _frameRate * 1E3;
	}

	//-------------------------------------------------------------------------
	//
	//  Public class methods
	//
	//-------------------------------------------------------------------------

	public static function set frameRate(value:uint):void {
		if ( _frameRate == value ) return;
		_frameRate = 1E3 / value;
	}

	

	//-------------------------------------------------------------------------
	//
	//  Constructor
	//
	//-------------------------------------------------------------------------

	/**
	 * Constructor 
	 * 
	 * @param delay
	 */
	public function FrameTimer(delay:Number) {
		super( delay );
		this._delay = delay;
		this.updateDelay();
	}

	//-------------------------------------------------------------------------
	//
	//  Private constants
	//
	//-------------------------------------------------------------------------

	private const _event_timer:	TimerEvent = new TimerEvent( TimerEvent.TIMER );

	//-------------------------------------------------------------------------
	//
	//  Private variables
	//
	//-------------------------------------------------------------------------

	private var _delay:Number;

	private var _count:uint = 0;

	private var _reset_count:uint = 1;

	//-------------------------------------------------------------------------
	//
	//  Properties
	//
	//-------------------------------------------------------------------------

	//---------------------------------
	//  delay
	//---------------------------------

	public override function get delay():Number {
		return this._delay;
	}

	public override function set delay(value:Number):void {
		if ( this._delay == value ) return;
		this._delay = value;
		this.updateDelay();
	}

	//---------------------------------
	//  currentCount
	//---------------------------------

	[Deprecated(message="deprecated")]
	/**
	 * @private
	 */
	public override function get currentCount():int {
		return 0;
	}

	[Deprecated(message="deprecated")]
	/**
	 * @private
	 */
	public override function set repeatCount(value:int):void {
		throw new IllegalOperationError();
	}

	//---------------------------------
	//  running
	//---------------------------------

	private var _running:Boolean = false;

	public override function get running():Boolean {
		return this._running;
	}


	//-------------------------------------------------------------------------
	//
	//  Public methods
	//
	//-------------------------------------------------------------------------

	public override function start():void {
		this.updateDelay();
		switch ( this._reset_count ) {
			case 0:		super.start();																			break;
			case 1:		enterFrameBroadcaster.addEventListener( Event.ENTER_FRAME, this.handler_enterFrame );	break;
			default:	enterFrameBroadcaster.addEventListener( Event.ENTER_FRAME, this.handler_enterFrame2 );	break;
				
		}
		this._running = true;
	}

	public override function stop():void {
		switch ( this._reset_count ) {
			case 0:		super.stop();																				break;
			case 1:		enterFrameBroadcaster.removeEventListener( Event.ENTER_FRAME, this.handler_enterFrame );	break;
			default:	enterFrameBroadcaster.removeEventListener( Event.ENTER_FRAME, this.handler_enterFrame2 );	break;
				
		}
		this._running = false;
	}

	[Deprecated(message="deprecated")]
	/**
	 * @private
	 */
	public override function reset():void {
		throw new IllegalOperationError();
	}

	//-------------------------------------------------------------------------
	//
	//  Private methods
	//
	//-------------------------------------------------------------------------

	/**
	 * @private 
	 */
	private function updateDelay():void {
		var value:Number = this._delay;
		var frame:Number = _frameRate;
		if ( value < frame ) {
			value = frame;
		}
		if ( super.delay == value ) return;
		super.delay = value;

		var reset_count:uint = Math.round( value / frame );

		if ( reset_count > 3.15 || Math.abs( value - frame * reset_count ) > frame * 0.15 ) {
			reset_count = 0;
		}

		if ( super.running && this._reset_count != reset_count ) {
			this.stop();
			this._reset_count = reset_count;
			this.start();
		} else {
			this._reset_count = reset_count;
		}
	}

	//-------------------------------------------------------------------------
	//
	//  Event handlers
	//
	//-------------------------------------------------------------------------
	/**
	 * @private 
	 */
	private function handler_enterFrame(event:Event):void {
		super.dispatchEvent( this._event_timer );
	}

	/**
	 * @private 
	 */
	private function handler_enterFrame2(event:Event):void {
		if ( ++this._count % this._reset_count ) {
			super.dispatchEvent( this._event_timer );
		}
	}

}
}